﻿using cmdb.keede.entity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using cmdb.keede.common;
using System.Threading.Tasks;

namespace cmdb.keede.data
{
    public abstract class RepositoryBase<T> where T : class
    {
        private readonly DbSet<T> dbset;
        protected RepositoryBase(CMDBContext dataContext)
        {
            this.DataContext = dataContext;
            dbset = DataContext.Set<T>();
        }
        protected CMDBContext DataContext { get; }
        public virtual void Add(T entity)
        {
            dbset.Add(entity);
        }
        public virtual void Update(T entity)
        {
            dbset.Attach(entity);
            DataContext.Entry(entity).State = EntityState.Modified;
        }
        public virtual void Delete(T entity)
        {
            dbset.Remove(entity);
        }
        public virtual void Delete(Expression<Func<T, bool>> where)
        {
            IEnumerable<T> objects = dbset.Where<T>(where).AsEnumerable();
            foreach (T obj in objects)
                dbset.Remove(obj);
        }
        public virtual Task<T> GetByIdAsync(int id)
        {
            return dbset.FindAsync(id);
        }
        public virtual Task<T> GetByIdAsync(string id)
        {
            return dbset.FindAsync(id);
        }
        public virtual Task<T> GetByIdAsync(Guid id)
        {
            return dbset.FindAsync(id);
        }
        public virtual Task<bool> AnyAsync(Expression<Func<T, bool>> any)
        {
            return dbset.AnyAsync(any);
        }
        public virtual Task<List<T>> GetAllAsync()
        {
            return dbset.ToListAsync();
        }
        public virtual IQueryable<T> GetQueryable()
        {
            return dbset;
        }

        public virtual IQueryable<T> GetQueryable(Expression<Func<T, bool>> where)
        {
            return dbset.Where(where);
        }

        public virtual async Task<IEnumerable<T>> GetManyAsync(Expression<Func<T, bool>> where)
        {
            return await dbset.Where(where).ToListAsync();
        }
        /// <summary>
        /// Return a paged list of entities
        /// </summary>
        /// <typeparam name="TOrder">T</typeparam>
        /// <param name="pager">Which page to retrieve</param>
        /// <param name="where">Where clause to apply</param>
        /// <param name="order">Order by to apply</param>
        /// <param name="isDesc">Is Desc</param>
        /// <returns></returns>
        public virtual async Task<BizResult<List<T>>> GetPageAsync<TOrder>(Pager pager, Expression<Func<T, bool>> where, Expression<Func<T, TOrder>> order, bool isDesc = true)
        {
            var results = isDesc ? dbset.OrderByDescending(order).Where(where).GetPage(pager) :
                                       dbset.OrderBy(order).Where(where).GetPage(pager);

            var total = await dbset.CountAsync(where);
            return new BizResult<List<T>>(await results.ToListAsync(), new Pager(pager.PageIndex, pager.PageSize, total));
        }

        //public virtual async Task<BizResult<IQueryable>> GetQueryablePageAsync<TOrder>(Pager pager, Expression<Func<T, bool>> where, Expression<Func<T, TOrder>> order, bool isDesc = true)
        //{
        //    var results = isDesc ? dbset.OrderByDescending(order).Where(where).GetPage(pager) :
        //        dbset.OrderBy(order).Where(where).GetPage(pager);

        //    var total = await dbset.CountAsync(where);
        //    return new BizResult<IQueryable>(results, new Pager(pager.PageIndex, pager.PageSize, total));
        //}

        public virtual Task<T> GetAsync(Expression<Func<T, bool>> where)
        {
            return dbset.Where(where).FirstOrDefaultAsync<T>();
        }
    }
}
